/* -------------------------------------------------------------------------
 *
 * block.h
 *	  openGauss disk block definitions.
 *
 *
 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/buf/block.h
 *
 * -------------------------------------------------------------------------
 */
#ifndef BLOCK_H
#define BLOCK_H

/*
 * BlockNumber:
 *
 * each data file (heap or index) is divided into openGauss disk blocks
 * (which may be thought of as the unit of i/o -- a openGauss buffer
 * contains exactly one disk block).  the blocks are numbered
 * sequentially, 0 to 0xFFFFFFFE.
 *
 * InvalidBlockNumber is the same thing as P_NEW in buf.h.
 *
 * the access methods, the buffer manager and the storage manager are
 * more or less the only pieces of code that should be accessing disk
 * blocks directly.
 */
typedef uint32 BlockNumber;

#define InvalidBlockNumber ((BlockNumber)0xFFFFFFFF)

#define MaxBlockNumber ((BlockNumber)0xFFFFFFFE)

typedef double RelPageType;

/*
 * BlockId:
 *
 * this is a storage type for BlockNumber.	in other words, this type
 * is used for on-disk structures (e.g., in HeapTupleData) whereas
 * BlockNumber is the type on which calculations are performed (e.g.,
 * in access method code).
 *
 * there doesn't appear to be any reason to have separate types except
 * for the fact that BlockIds can be SHORTALIGN'd (and therefore any
 * structures that contains them, such as ItemPointerData, can also be
 * SHORTALIGN'd).  this is an important consideration for reducing the
 * space requirements of the line pointer (ItemIdData) array on each
 * page and the header of each heap or index tuple, so it doesn't seem
 * wise to change this without good reason.
 */
typedef struct BlockIdData {
    uint16 bi_hi;
    uint16 bi_lo;
} BlockIdData;

typedef BlockIdData* BlockId; /* block identifier */

/* Data structure for Algorithm S from Knuth 3.4.2 */
typedef struct {
    BlockNumber N; /* number of blocks, known in advance */
    int n;         /* desired sample size */
    BlockNumber t; /* current block number */
    int m;         /* blocks selected so far */
} BlockSamplerData;

typedef BlockSamplerData* BlockSampler;

void BlockSampler_Init(BlockSampler bs, BlockNumber nblocks, int samplesize);
bool BlockSampler_HasMore(BlockSampler bs);
BlockNumber BlockSampler_Next(BlockSampler bs);

/* ----------------
 *		support macros
 * ----------------
 */

/*
 * BlockNumberIsValid
 *		True iff blockNumber is valid.
 */
#define BlockNumberIsValid(blockNumber) ((bool)((BlockNumber)(blockNumber) != InvalidBlockNumber))

/*
 * BlockIdIsValid
 *		True iff the block identifier is valid.
 */
#define BlockIdIsValid(blockId) ((bool)PointerIsValid(blockId))

/*
 * BlockIdSet
 *		Sets a block identifier to the specified value.
 */
#define BlockIdSet(blockId, blockNumber)        \
    (AssertMacro(PointerIsValid(blockId)),      \
        (blockId)->bi_hi = (blockNumber) >> 16, \
        (blockId)->bi_lo = (blockNumber)&0xffff)

/*
 * BlockIdCopy
 *		Copy a block identifier.
 */
#define BlockIdCopy(toBlockId, fromBlockId)        \
    (AssertMacro(PointerIsValid(toBlockId)),       \
        AssertMacro(PointerIsValid(fromBlockId)),  \
        (toBlockId)->bi_hi = (fromBlockId)->bi_hi, \
        (toBlockId)->bi_lo = (fromBlockId)->bi_lo)

/*
 * BlockIdEquals
 *		Check for block number equality.
 */
#define BlockIdEquals(blockId1, blockId2) \
    ((blockId1)->bi_hi == (blockId2)->bi_hi && (blockId1)->bi_lo == (blockId2)->bi_lo)

/*
 * BlockIdGetBlockNumber
 *		Retrieve the block number from a block identifier.
 */
#define BlockIdGetBlockNumber(blockId) \
    (AssertMacro(BlockIdIsValid(blockId)), (BlockNumber)(((blockId)->bi_hi << 16) | ((uint16)(blockId)->bi_lo)))

#endif /* BLOCK_H */
